import java.io.IOException;
import java.util.ArrayList;


public class FrameMotionParser implements IParser{
	private VideoFile videoFile;
	private IColorStrategy colorMethod;
	private FrameMotionInfo[] motionInfos; //The last frame does NOT have motion info
	
	public FrameMotionParser(VideoFile videoFile){
		this.videoFile = videoFile;
		this.colorMethod = new SignGrayCode();
		
		//Initialize informations of all video frames
		motionInfos = new FrameMotionInfo[(int)videoFile.getTotalFrameNumber()];
	}
	
	public void parse(VideoSegment[] segments){
		System.out.println("Motion information parsing starts");
		double maxWeight = 0;
		for(int i=0; i<segments.length ; ++i){
			if (segments[i] == null)
				continue;
			
			ArrayList<Integer> keyFrames = segments[i].keyFrames;
			for(int j=0; j<keyFrames.size(); j++){
				int end = keyFrames.get(j) + 24;
				if (end > segments[i].end){
					end =  segments[i].end;
				}
			    calcFrameMotionInfos(keyFrames.get(j), end);
			}
			
			double sum = 0;
			int count = 0;
			for(int j=segments[i].start; j<=segments[i].end; j++){
				if(motionInfos[j] != null){
					sum += motionInfos[j].modSum;
					count++;
				}
			}
			sum /= count;
			segments[i].setMotionWeight(sum);
			if(sum > maxWeight)
				maxWeight = sum;
			System.out.println("segment "+i+" done");
		} 
		for(int i=0; i<segments.length; i++){
			if (segments[i] != null)
				segments[i].motionWeight /= maxWeight;
		}
	}
	
	public FrameMotionInfo[] getFrameMotionInfos(){
		return motionInfos;
	}
	
	private int calcFrameMotionInfos(int start, int end){
		if (end >= motionInfos.length-1){
			end = motionInfos.length - 2;
		}
		if (start > end)
			return 0;
		
		int[][] prevData = new int[videoFile.getHeight()][videoFile.getWidth()];
		int[][] nextData = new int[videoFile.getHeight()][videoFile.getWidth()];
		int[][] temp;
		
		try{
			videoFile.setFramePosition(start);
			getGrayData(prevData);
			for(int i=start; i<=end; ++i){
				getGrayData(nextData);
				motionInfos[i] = new FrameMotionInfo();
				motionInfos[i].calcVectorsUsingARPS(prevData, nextData);
				//motionInfos[i].calcVectorsUsingBruteForce(prevData, nextData);
				motionInfos[i].calMotionSum();
				//motionInfos[i].print();
				//Step data
				temp = prevData;
				prevData = nextData;
				nextData = temp;
			}
		}catch (IOException e){
			e.printStackTrace();
			return 0;
		}
		
		return end - start + 1;
	}
	
	private void getGrayData(int[][] grayData) throws IOException{
		byte[] rgbData;
		rgbData = videoFile.readRawData();
		int size = grayData.length * grayData[0].length;
		int doubleSize = size + size;
		int ind = 0;
		for (int y=0; y<grayData.length; ++y){
			for(int x=0; x<grayData[0].length; ++x){
				grayData[y][x] = colorMethod.combineColorCode(
						rgbData[ind], 
						rgbData[ind+size], 
						rgbData[ind+doubleSize]);
				++ind;
			}
		}
	}
}
